﻿using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Text;
using System.Configuration;

using BizElements.BusinessLayer;

namespace BizElements.Web
{
    /// <summary>
    /// <see cref="DataGrid"/> template which displays and edits the value of a bound field in a <see cref="BoundCheckBox"/> control.
    /// </summary>
    public class BoundCheckBoxTemplate : BoundTemplateBase
    {
        #region Fields.

        object falseValue = false;
        object trueValue = true;

        #endregion

        #region Constructors.

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundCheckBoxTemplate"/> class.
        /// </summary>
        public BoundCheckBoxTemplate()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundCheckBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        public BoundCheckBoxTemplate(IBindableField field, IMessageFormatter formatter)
            : base(field, formatter)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundCheckBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="skinID">The skin to apply to the controls generated by this template.</param>
        public BoundCheckBoxTemplate(IBindableField field, IMessageFormatter formatter, string skinID)
            : base(field, formatter, skinID)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundCheckBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="width">The width of check box used in the template.</param>
        /// <param name="cssClass">CSS Class name applied to check box created by the template.</param>
        /// <param name="readOnlyCss">CSS Class name applied to controls created by the template when in read-only mode.</param>
        public BoundCheckBoxTemplate(IBindableField field, IMessageFormatter formatter, int width, string cssClass, string readOnlyCss)
            : base(field, formatter, width, cssClass, readOnlyCss)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundCheckBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="trueValue">The value used in bound field instead of <b>true</b>.</param>
        /// <param name="falseValue">The value used in bound field instead of <b>false</b>.</param>
        public BoundCheckBoxTemplate(IBindableField field, IMessageFormatter formatter, object trueValue, object falseValue)
            : base(field, formatter)
        {
            this.trueValue = trueValue;
            this.falseValue = falseValue;
        }

        #endregion

        #region Properties.

        /// <summary>
        /// Gets or sets the value used in bound field instead of <b>true</b>.
        /// </summary>
        /// <value>A true/yes indicator. Default is <b>true</b>.</value>
        public virtual object TrueValue
        {
            get { return this.trueValue; }
            set { this.trueValue = value; }
        }

        /// <summary>
        /// Gets or sets the value used in bound field instead of <b>false</b>.
        /// </summary>
        /// <value>A false/no indicator. Default is <b>false</b>.</value>
        public virtual object FalseValue
        {
            get { return this.falseValue; }
            set { this.falseValue = value; }
        }

        #endregion

        #region Methods.

        /// <summary>
        /// Defines the <see cref="DataGrid"/> that child check box controls and the template belong to.
        /// </summary>
        /// <param name="container">The <b>TableCell</b> which contains the controls instantiated by this template.</param>
        public override void InstantiateIn(Control container)
        {
            BoundCheckBox chkbox = new BoundCheckBox();
            chkbox.DataBinding += new EventHandler(this.BindDisplayValue);
            if (this.SkinID != null)
            {
                chkbox.SkinID = this.SkinID;
                Page page = HttpContext.Current.Handler as Page;
                if (page != null)
                    chkbox.ApplyStyleSheetSkin(page);
            }

            container.Controls.Add(chkbox);
        }

        private void BindDisplayValue(object sender, EventArgs e)
        {
            BoundCheckBox chkbox = (BoundCheckBox)sender;
            ApplyStyle(chkbox);
            chkbox.TrueValue = this.TrueValue;
            chkbox.FalseValue = this.FalseValue;

            DataGridItem currentItem = (DataGridItem)chkbox.NamingContainer;
            object val = DataBinder.Eval(currentItem.DataItem, this.BoundField.BindingName);
            var twoWayProperty = ControlPropertyBinderFactory.CreateBindableControlProperty(chkbox);
            twoWayProperty.SetValue(chkbox, chkbox.TwoWayBoundProperty, val, this.Formatter);

            bool isReadOnly = ConfigureAccessMode(chkbox);
            if (isReadOnly)
            {
                chkbox.BackColor = Color.Transparent;
                chkbox.Style["cursor"] = "pointer";
            }
        }

        #endregion
    }
}